package org.zwy.gradetrack.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.zwy.gradetrack.common.Result;
import org.zwy.gradetrack.entity.User;
import org.zwy.gradetrack.entity.OperationLog;
import org.zwy.gradetrack.service.UserService;
import org.zwy.gradetrack.service.OperationLogService;
import org.zwy.gradetrack.security.JwtTokenUtil;
import org.zwy.gradetrack.common.Constants;
import org.zwy.gradetrack.entity.Role;
import org.zwy.gradetrack.service.RoleService;
import org.springframework.security.access.prepost.PreAuthorize;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 认证控制器
 */
@RestController
@RequestMapping("/api/auth")
public class AuthController {

    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserService userService;

    @Autowired
    private OperationLogService operationLogService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RoleService roleService;

    /**
     * 用户登录
     */
    @PostMapping("/login")
    public Result<Map<String, Object>> login(@RequestBody Map<String, String> loginForm) {
        String username = loginForm.get("username");
        String password = loginForm.get("password");

        logger.info("用户尝试登录: {}", username);

        try {
            // 获取用户信息
            User user = userService.lambdaQuery()
                    .eq(User::getUsername, username)
                    .one();

            if (user == null) {
                logger.error("用户不存在: {}", username);
                return Result.error(Constants.BAD_REQUEST, "用户名或密码错误");
            }

            logger.info("数据库中的密码: {}", user.getPassword());
            logger.info("输入的密码: {}", password);

            // 使用Spring Security进行认证
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(username, password)
            );
            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 生成JWT token
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            String token = jwtTokenUtil.generateToken(userDetails);

            // 记录登录日志
            OperationLog log = new OperationLog();
            log.setUserId(user.getId());
            log.setOperationModule("用户认证");
            log.setOperationType("登录");
            log.setOperationDesc("用户登录");
            log.setOperationTime(LocalDateTime.now());
            operationLogService.save(log);

            // 返回用户信息和token
            Map<String, Object> result = new HashMap<>();
            result.put("token", "Bearer " + token);
            result.put("user", user);

            // 获取用户角色并添加到结果中
            List<Role> roles = roleService.getRolesByUserId(user.getId());
            if (!roles.isEmpty()) {
                // 假设我们只返回第一个角色代码作为用户的当前角色
                result.put("userRoleCode", roles.get(0).getRoleCode());
            } else {
                result.put("userRoleCode", "GUEST"); // 如果没有角色，默认为GUEST
            }

            logger.info("用户登录成功: {}", username);
            return Result.success(result);
        } catch (Exception e) {
            logger.error("登录失败: {}", e.getMessage(), e);
            return Result.error(Constants.BAD_REQUEST, "用户名或密码错误");
        }
    }

    /**
     * 用户注册
     */
    @PostMapping("/register")
    public Result<Void> register(@RequestBody User user) {
        // 检查用户名是否已存在
        if (userService.lambdaQuery()
                .eq(User::getUsername, user.getUsername())
                .exists()) {
            return Result.error(Constants.BAD_REQUEST, "用户名已存在");
        }

        // 加密密码
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        
        // 设置默认值
        user.setStatus(Constants.USER_STATUS_ENABLED);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 保存用户
        userService.save(user);

        // 记录注册日志
        OperationLog log = new OperationLog();
        log.setUserId(user.getId());
        log.setOperationType("注册");
        log.setOperationDesc("用户注册");
        log.setOperationTime(LocalDateTime.now());
        operationLogService.save(log);

        return Result.success();
    }

    /**
     * 获取当前用户信息
     */
    @GetMapping("/info")
    public Result<User> getUserInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();

        User user = userService.lambdaQuery()
                .eq(User::getUsername, username)
                .one();

        if (user == null) {
            return Result.error(Constants.NOT_FOUND, "用户不存在");
        }

        return Result.success(user);
    }

    /**
     * 修改密码
     */
    @PostMapping("/password")
    public Result<Void> changePassword(@RequestBody Map<String, String> passwordForm) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();

        String oldPassword = passwordForm.get("oldPassword");
        String newPassword = passwordForm.get("newPassword");

        User user = userService.lambdaQuery()
                .eq(User::getUsername, username)
                .one();

        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            return Result.error(Constants.BAD_REQUEST, "原密码错误");
        }

        user.setPassword(passwordEncoder.encode(newPassword));
        user.setUpdateTime(LocalDateTime.now());
        userService.updateById(user);

        // 记录修改密码日志
        OperationLog log = new OperationLog();
        log.setUserId(user.getId());
        log.setOperationType("修改密码");
        log.setOperationDesc("用户修改密码");
        log.setOperationTime(LocalDateTime.now());
        operationLogService.save(log);

        return Result.success();
    }

    /**
     * 更新个人信息
     */
    @PutMapping("/profile")
    @PreAuthorize("isAuthenticated()")
    public Result<User> updateProfile(@RequestBody User userUpdates) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();

        User currentUser = userService.lambdaQuery()
                .eq(User::getUsername, username)
                .one();

        if (currentUser == null) {
            return Result.error(Constants.NOT_FOUND, "用户不存在");
        }

        // 仅允许更新部分字段
        currentUser.setRealName(userUpdates.getRealName());
        currentUser.setEmail(userUpdates.getEmail());
        currentUser.setPhone(userUpdates.getPhone());
        currentUser.setUpdateTime(LocalDateTime.now());

        userService.updateById(currentUser);

        // 记录操作日志
        OperationLog log = new OperationLog();
        log.setUserId(currentUser.getId());
        log.setOperationModule("个人信息管理");
        log.setOperationType("更新");
        log.setOperationDesc("更新个人信息");
        log.setOperationTime(LocalDateTime.now());
        operationLogService.save(log);

        return Result.success(currentUser);
    }

    /**
     * 获取当前用户的权限信息 (DEBUG ENDPOINT)
     */
    @GetMapping("/user/authorities")
    @PreAuthorize("isAuthenticated()") // 只要求认证，不要求特定角色
    public Result<List<String>> getCurrentUserAuthorities() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.isAuthenticated()) {
            List<String> authorities = authentication.getAuthorities().stream()
                    .map(grantedAuthority -> grantedAuthority.getAuthority())
                    .collect(Collectors.toList());
            return Result.success(authorities);
        }
        return Result.error(401, "用户未认证");
    }
} 